﻿using Furion;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using JoyAdmin.Core.Model;
using JoyAdmin.Core;
using DX_Common.AgreementEntity;
using DX_Common.Common;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Data;
using System.Threading;
using DX_Common.Model;
using Microsoft.AspNetCore.Http;
using System.Net.Sockets;
using System.Net;
using System.Text;

namespace JoyAdmin.Application
{
    public class AddAgreeMent
    {
        /// <summary>
        /// 客户ID
        /// </summary>
        public int Id { get; set; }
        /// <summary>
        /// 客户名称
        /// </summary>
        [Required(ErrorMessage = "协议名称不能为空")]
        public string AgreeMentName { get; set; }
        [Required(ErrorMessage = "协议类型不能为空")]
        public string AgreeType { get; set; }
        public string Des { get; set; }

    }

    /// <summary>
    /// 协议服务
    /// </summary>
    public class AgreementService : IDynamicApiController
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        public AgreementService(IHttpContextAccessor httpContextAccessor) 
        {
            _httpContextAccessor = httpContextAccessor;
        }


        /// <summary>
        /// 刷新模拟协议报文
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public string EditForwardRefreshMessage(TransDevice input)
        {
            // 找协议
            String AgreementName = Convert.ToString(input.AgreeName.Replace("\r\n", "")); //sl651
            Type t = AgreementLoad.ListAgreementClass.Where(x => x.Name == AgreementName).FirstOrDefault();
            if (t == null)
            {
                throw Oops.Oh(ErrorCode.WrongValidation, "未找到协议类:" + AgreementName).StatusCode(ErrorStatus.ValidationFaild);
            }

            try
            {
                //加载实例化协议
                var tmpClass = (IbaseAgreement)Activator.CreateInstance(t);

                List<EssDataModelJSON> listModel = new List<EssDataModelJSON>();
                EssDataModelJSON essDataModel = new EssDataModelJSON();
                essDataModel.ST = input.DeviceNo;
                essDataModel.TT = "2024-09-09 11:20:00.000";
                essDataModel.TYPE = "OVERTIME";
                essDataModel.SERIAL = 2023;
                essDataModel.TELTYPE = 1;
                essDataModel.ESS = "Z";
                essDataModel.SDATA = "3.141";
                essDataModel.DATA = 3.141;
                essDataModel.UT = "2024-09-09 11:25:50.000";
                essDataModel.STT = "2024-09-09 11:39:07.587";
                listModel.Add(essDataModel);

                DataTable namesTable = new DataTable();
                namesTable.Columns.Add("Agreement_Json");
                namesTable.Columns.Add("ExternalDeviceNo");
                namesTable.Columns.Add("DeviceNo");
                namesTable.Columns.Add("EssCode");

                DataRow rwpz = namesTable.NewRow();
                rwpz["Agreement_Json"] = input.AgreeMent_Json;
                rwpz["ExternalDeviceNo"] = input.ExternalDeviceNo;
                rwpz["DeviceNo"] = input.DeviceNo;
                rwpz["EssCode"] = input.EssCode;


                // 判断发送类型
                switch (tmpClass.Transfertype)
                {
                    case AgreementTransferype.tcp:
                    case AgreementTransferype.udp:
                        //拼接发送数据 写入参数
                        Tuple<bool, Byte[]> tfmessage = tmpClass.SplicedSendMessage<Byte[]>(rwpz, listModel);
                        if (tfmessage.Item1)
                        {
                            return (TransData.ConvertDataBySpace(tfmessage.Item2));
                          
                        }
                        break;
                    case AgreementTransferype.httpPost:
                        //拼接发送数据 写入参数
                        Tuple<bool, string> tfmessage1 = tmpClass.SplicedSendMessage<string>(rwpz, listModel);
                        if (tfmessage1.Item1)
                        {
                            return (tfmessage1.Item2);

                        }
                        break;
                    case AgreementTransferype.mqtt:
                        break;
                    case AgreementTransferype.ftp:
                        break;
                }
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ErrorCode.WrongValidation, ex.ToString()).StatusCode(ErrorStatus.ValidationFaild);
            }
            return "";
        }

        /// <summary>
        /// 测试发送数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public string TestSendingData(TransDevice input)
        {
            // 找协议
            String AgreementName = Convert.ToString(input.AgreeName.Replace("\r\n", "")); //sl651
            Type t = AgreementLoad.ListAgreementClass.Where(x => x.Name == AgreementName).FirstOrDefault();
            if (t == null)
            {
                throw Oops.Oh(ErrorCode.WrongValidation, "未找到协议类:" + AgreementName).StatusCode(ErrorStatus.ValidationFaild);
            }

            try
            {
                //加载实例化协议
                var tmpClass = (IbaseAgreement)Activator.CreateInstance(t);
                //t.GetMethod("SplicedSendMessage").Invoke(tmpClass, new object[] { });
                bool issendok = false;
                // 判断发送类型
                switch (tmpClass.Transfertype)
                {
                    case AgreementTransferype.tcp:
                        Socket m_socket = blOpenTcpClient(input.Reladdress, Convert.ToInt32(input.Port));
                        if (m_socket == null)
                        {
                            throw Oops.Oh(ErrorCode.WrongValidation, "Socket 连接失败").StatusCode(ErrorStatus.ValidationFaild);
                        }
                        m_socket.Send(TransData.ConvertHexStringToBytes(input.AgreeExample));
                        issendok = true;
                        break;
                    case AgreementTransferype.udp:
                        Socket m_socketudp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

                        IPEndPoint ip = new IPEndPoint(IPAddress.Parse(input.Reladdress), Convert.ToInt32(input.Port));
                        m_socketudp.SendTo(TransData.ConvertHexStringToBytes(input.AgreeExample), ip);
                        issendok = true;
                        Thread.Sleep(200);
                        m_socketudp.Close();
                        break;
                    case AgreementTransferype.httpPost:
                        string result = tmpClass.PostUrl(input.Reladdress, input.AgreeExample);

                        issendok = true;
                        break;
                    case AgreementTransferype.mqtt:
                        break;
                    case AgreementTransferype.ftp:
                        break;
                }
                if (issendok)
                {
                    //如果发送成功则 把协议名和时间 放到表里
                    return (AgreementName + " 协议测试发送成功");
                }
                else
                {
                    // 如果发送失败
                    return (AgreementName + " 协议测试发送失败");
                }
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ErrorCode.WrongValidation, ex.ToString()).StatusCode(ErrorStatus.ValidationFaild);
            }
        }

        public static Socket blOpenTcpClient(string ipString, int port)
        {
            Socket clientSocket = null;
            //连接
            try
            {
                IPAddress ip = IPAddress.Parse(ipString);
                IPEndPoint remoteEndPoint = new IPEndPoint(ip, port);
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.SendTimeout = 2000;     //2s内，要求数据包发出
                clientSocket.ReceiveTimeout = 2000;  //2s内，要求应答消息收到

                try
                {
                    clientSocket.Connect(remoteEndPoint);
                    return clientSocket;
                }
                catch (Exception ex)
                {
                    //Messages.SaveLog(ex);
                    return null;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }


    }

    public class AgreementLoad : AppStartup
    {
        public static List<Type> ListAgreementClass = new List<Type>();
        public void ConfigureServices(IServiceCollection services)
        {
            string dir = "D:\\DB";
            string[] allDll = Directory.GetFiles(dir, "*.dll");
            foreach (var fdll in allDll.OrderBy(f =>File.GetLastWriteTime(f)))
            {
                LoadDllLoadMenu(fdll);
            }

            // 创建FileSystemWatcher对象并设置要监视的目录
            FileSystemWatcher watcher = new FileSystemWatcher(dir);
            // 设置监视的文件类型
            watcher.Filter = "*.dll";


            // 设置监控的事件类型
            watcher.NotifyFilter = NotifyFilters.LastWrite
                                 | NotifyFilters.FileName
                                 | NotifyFilters.DirectoryName;


            // 监视子目录
            watcher.IncludeSubdirectories = true;

            // 定义事件处理器
            watcher.Created += (source, fsea) =>
            {
                // 打印发生的事件
                //Console.WriteLine($"{fsea.FullPath} - {fsea.ChangeType}");
                Thread.Sleep(6000);
                LoadDllLoadMenu(fsea.FullPath);
            };
            watcher.Deleted += (source, fsea) =>
            {
               
            }; ;
            watcher.Changed += (source, fsea) =>
            {
               
            }; ;
            watcher.Renamed += (source, fsea) =>
            {
               
            }; ;

            // 只当需要时启动监控
            watcher.EnableRaisingEvents = true;
            Console.WriteLine("协议文件夹监控启动。。。");


            // 关闭监控
            //watcher.EnableRaisingEvents = false;

        }

        private static void LoadDllLoadMenu(string FullPath)
        {
            try
            {
                //动态加载程序集
                Assembly assembly = Assembly.LoadFile(FullPath);
                if (assembly != null)
                {
                    IEnumerable<Type> wormMain = assembly.GetTypes().Where(t => !t.IsAbstract && t.IsClass);
                    foreach (Type t in wormMain)
                    {
                        ListAgreementClass.Remove(ListAgreementClass.Where(c => c.Name == t.Name).FirstOrDefault());

                        ListAgreementClass.Add(t);
                    }
                }
            }
            catch (Exception ex)
            {
                throw Oops.Oh(ErrorCode.WrongValidation, "加载协议类异常:" + FullPath).StatusCode(ErrorStatus.ValidationFaild);
            }
        }
    }
}